import datetime
import hashlib
import random
import time

from django.db import transaction
from rest_framework import serializers, status, exceptions

from rest_framework.serializers import ModelSerializer

from cards.api.utils import str2md5
from cards.models import Card, RetailerCard, CardDepositRecord, GiftCard, UserGiftCard, CardConsumeRecord, SampleCard, \
    ClientSampleRecord, BalanceBill
from wxchat.api.utils import get_user_by_openid


class CardSerializer(ModelSerializer):
    """
    制卡
    """
    # retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    status = serializers.SerializerMethodField(read_only=True)
    image = serializers.ImageField(allow_null=True, label='卡图片', required=False, read_only=True)

    class Meta:
        model = Card
        exclude = ["update_time", "add_time"]

    def get_status(self, obj):
        if obj.begin_date and obj.end_date and obj.begin_date <= datetime.datetime.now().date() <= obj.end_date:
            return 0
        return 1


class RetailerCardSerializer(ModelSerializer):
    """
    商家卡
    """
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    card_name = serializers.CharField(source='card.name', read_only=True)
    # card_image = serializers.CharField(source='card.image.url', read_only=True)
    card_image = serializers.SerializerMethodField(read_only=True)
    amount = serializers.CharField(source='card.amount', read_only=True)
    ack_name = serializers.CharField(source='get_ack_display', read_only=True)
    update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)

    class Meta:
        model = RetailerCard
        exclude = ["add_time"]

    def get_card_image(self, obj):
        return obj.card.image.url if obj.card.image else ''


class CardDepositRecordSerializer(ModelSerializer):
    """
    用户购卡记录表
    """
    retailer_name = serializers.CharField(source="retailer.name", read_only=True)
    r_card_name = serializers.CharField(source="r_card.card.name", read_only=True)
    status_name = serializers.CharField(source="get_status_display", read_only=True)
    pay_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)

    class Meta:
        model = CardDepositRecord
        exclude = ["update_time", "add_time"]


class GiftCardSerializer(ModelSerializer):
    """
    赠送卡
    """
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    card_retailer_name = serializers.CharField(source='r_card.retailer.name', read_only=True)
    r_card_name = serializers.CharField(source='r_card.card.name', read_only=True)
    r_card_image = serializers.SerializerMethodField(read_only=True)
    r_card_amount = serializers.CharField(source='r_card.card.amount', read_only=True)
    update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    cancel_flag = serializers.SerializerMethodField(read_only=True)
    status_name = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = GiftCard
        exclude = ["add_time"]

    def get_cancel_flag(self, obj):
        curr_datetime = datetime.datetime.now()
        diff_hour = (curr_datetime - obj.update_time).total_seconds() / 3600
        return diff_hour <= 24

    def get_r_card_image(self, obj):
        return obj.r_card.card.image.url if obj.r_card.card.image else ''


class UserGiftCardSerializer(ModelSerializer):
    """
    客户会员卡
    """
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    r_card_name = serializers.CharField(source='r_card.card.name', read_only=True)
    r_card_image = serializers.SerializerMethodField(read_only=True)
    r_card_amount = serializers.CharField(source='r_card.card.amount', read_only=True)

    class Meta:
        model = UserGiftCard
        exclude = ["update_time", "add_time"]

    def get_r_card_image(self, obj):
        return obj.r_card.card.image.url if obj.r_card.card.image else ''


class CardConsumeRecordSerializer(ModelSerializer):
    """
    客户会员卡消费记录
    """
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    card_retailer_name = serializers.CharField(source='r_card.retailer.name', read_only=True)
    r_card_name = serializers.CharField(source='r_card.card.name', read_only=True)
    r_card_amount = serializers.CharField(source='r_card.card.amount', read_only=True)
    r_card_image = serializers.SerializerMethodField(read_only=True)
    update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)

    class Meta:
        model = CardConsumeRecord
        exclude = ["add_time"]

    def get_r_card_image(self, obj):
        return obj.r_card.card.image.url if obj.r_card.card.image else ''


class SampleCardSerializer(ModelSerializer):
    """
    制卡
    """
    card_name = serializers.CharField(source='card.name', read_only=True)
    card_comment = serializers.CharField(source='card.comment', read_only=True)
    status_name = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = SampleCard
        exclude = ["add_time"]

    def create(self, validated_data):
        # 判断是否已经领取
        openid = validated_data.get("openid", None)
        card = validated_data.get("card", None)
        cur_date = datetime.datetime.now().date()
        if not Card.objects.filter(id=card.id, begin_date__lte=cur_date, end_date__gte=cur_date).exists():
            msg = {
                'status_code': status.HTTP_400_BAD_REQUEST,
                'message': '此次品鉴活动已经结束!'
            }
            raise exceptions.ValidationError(msg)

        exists = self.Meta.model.objects.filter(card=card, openid=openid).exists()
        if exists:
            msg = {
                'status_code': status.HTTP_400_BAD_REQUEST,
                'message': '您已领过,不能重复领取品鉴卡'
            }
            raise exceptions.ValidationError(msg)

        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()
            instance = None
            try:
                key = '{0}{1}{2}'.format(openid, card.id, time.time(), random.randint(10000, 100000))
                result = str2md5(key)
                print(key)
                print(result)
                validated_data["key"] = result
                if openid:
                    user = get_user_by_openid(openid)
                    validated_data["name"] = user.name or user.nickname

                instance = self.Meta.model.objects.create(**validated_data)

            except Exception as e:
                print("excetpion: ", e)
                transaction.savepoint_rollback(save_id)
                msg = {
                    'status_code': status.HTTP_400_BAD_REQUEST,
                    'message': '保存失败'
                }
                raise exceptions.ValidationError(msg)

            transaction.savepoint_commit(save_id)
        return instance


class ClientSampleRecordSerializer(ModelSerializer):
    """
    核销
    """
    card_name = serializers.CharField(source='card.name', read_only=True)
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)
    confirm_time = serializers.SerializerMethodField(read_only=True)
    flag_name = serializers.CharField(source="get_balance_flag_display", read_only=True)

    class Meta:
        model = ClientSampleRecord
        exclude = ["add_time"]

    def get_confirm_time(self, obj):
        return obj.add_time.strftime("%Y-%m-%d %H:%M:%S")


class BalanceBillSerializer(ModelSerializer):
    """
    结算单
    """
    retailer_name = serializers.CharField(source='retailer.name', read_only=True)

    class Meta:
        model = BalanceBill
        exclude = ["update_time", "add_time"]

